﻿using System;
using System.Configuration;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using RogerioCoimbra.DivulgacaoEspirita.Dominio.Entidade;

namespace RogerioCoimbra.DivulgacaoEspirita.Dominio.Repositorio
{
	/// <summary>
	///  Repositório base, contém as operações básicas de um repositório.
	/// </summary>
	public abstract class RepositorioBase<Entidade> where Entidade : EntityObject
	{
		#region Public
		/// <summary>
		/// Obtem todos os elementos da do tipo <typeparamref name="Entidade"/>.
		/// </summary>
		/// <returns>Lista de entidades</returns>
		public static List<Entidade> ObterTodos()
		{
			using (DivulgacaoEspiritaEntities objetoContexto = ObterContexto())
			{
				return ObterTodos(objetoContexto).ToList();
			}
		}

		/// <summary>
		/// Salva a entidade.
		/// </summary>
		public static void Inserir(Entidade entidade)
		{
			using (DivulgacaoEspiritaEntities objetoContexto = ObterContexto())
			{
				objetoContexto.AddObject(typeof(Entidade).Name, entidade);
				objetoContexto.SaveChanges();
			}
		}

		/// <summary>
		/// Atualiza a entidade.
		/// </summary>
		/// <param name="entidade"></param>
		public static void Atualizar(Entidade entidade)
		{
			using (DivulgacaoEspiritaEntities objetoContexto = ObterContexto())
			{
				//Cria a EntityKey da entidade.
				//entidade.EntityKey = objetoContexto.CreateEntityKey(typeof(Entidade).Name, entidade);

				//Anexa a entidade a ser atualizada no contexto.
				objetoContexto.Attach(entidade);

				//Marca propriedades como alteradas.
				//ObjectStateEntry stateEntry = objetoContexto.ObjectStateManager.GetObjectStateEntry(entidade.EntityKey);
				//IEnumerable<string> propertyNameList = stateEntry.CurrentValues.DataRecordInfo.FieldMetadata.Select(pn => pn.FieldType.Name);
				//foreach (string propName in propertyNameList)
				//{
				//    stateEntry.SetModifiedProperty(propName);
				//}

				//Salva atualizações.
				objetoContexto.SaveChanges();
			}
		}

		/// <summary>
		/// Exclui a entidade.
		/// </summary>
		/// <param name="entidade"></param>
		public static void Excluir(Entidade entidade)
		{
			using (DivulgacaoEspiritaEntities objetoContexto = ObterContexto())
			{
				//Marca a entidade para ser excluida.
				objetoContexto.DeleteObject(entidade);

				//Salva atualizações.
				objetoContexto.SaveChanges();
			}
		}
		#endregion

		#region Protected
		/// <summary>
		/// Obtem todos os elementos da do tipo <typeparamref name="Entidade"/>.
		/// </summary>
		/// <returns>Objeto de seleção do tipo Entidade</returns>
		protected static IQueryable<Entidade> ObterTodos(DivulgacaoEspiritaEntities objetoContexto)
		{
			return
				from entidade in objetoContexto.CreateQuery<Entidade>(String.Format("[{0}]", typeof(Entidade).Name))
				select entidade;

		}

        /// <summary>
        /// Obtem por condição.
        /// </summary>
        /// <param name="condicional"></param>
        /// <param name="objetoContexto"></param>
        /// <returns></returns>
        protected static IQueryable<Entidade> ObterPorCondicao(Expression<Func<Entidade, Boolean>> condicional, DivulgacaoEspiritaEntities objetoContexto)
        {
            return ObterTodos(objetoContexto).Where(condicional);
        }

		/// <summary>
		/// Obtem o objeto de contexto.
		/// </summary>
		/// <returns></returns>
		protected static DivulgacaoEspiritaEntities ObterContexto()
		{
			return new DivulgacaoEspiritaEntities();
		}
		#endregion
	}
}
